package geppetto.cat.corpus;

import gnu.trove.TIntIntHashMap;

/**
 * This class acts as a mapper from pairs of source word / foreign word to an
 * unique integer
 * 
 * @author javg
 * 
 */
public class Reference extends AbstractReferenceTable {

	TIntIntHashMap[] indices; // Index by source id give an IntIntHashMap that
								// for each foreign id as a unique integer

	int nrIndices;

	int addPos(int[] sourceSentence, int[] foreignSentence, int nrIndices) {
		// common.MyArrays.printIntArray(sourceSentence, "sourceSentence");
		// common.MyArrays.printIntArray(foreignSentence, "forSentence");
		for (int j = 0; j < sourceSentence.length; j++) {
			int sourcePos = sourceSentence[j];
			for (int k = 0; k < foreignSentence.length; k++) {
				int foreignPos = foreignSentence[k];
				if (indices[sourcePos] == null) {
					indices[sourcePos] = new TIntIntHashMap();
					indices[sourcePos].put(foreignPos, nrIndices);
					nrIndices++;
				} else if (!indices[sourcePos].contains(foreignPos)) {
					indices[sourcePos].put(foreignPos, nrIndices);
					nrIndices++;
				}
			}
		}
		return nrIndices;
	}

	// Slow method only good for debugging
	public void printReferencePos(BilingualCorpus corpus) {
		for (int i = 0; i < corpus.getSourceSize(); i++) {
			int[] pos = indices[i].keys();
			for (int j = 0; j < pos.length; j++) {
				System.out.print(" " + i + "-" + pos[j] + "-"
						+ indices[i].get(pos[j]) + " ");
			}

		}
	}

	@Override
	public void initialize(BilingualCorpus corpus) {
		// positions = new TIntIntHashMap();
		// System.out.println("Source " + corpus.getSourceSize());
		// System.out.println("Foreign " + corpus.getForeignSize());

		// Go for trainining sentence
		indices = new TIntIntHashMap[corpus.getSourceSize()];
		nrIndices = 0;
		
		for (int i = 0; i < corpus.getNumberOfTrainingSentences(); i++) {
			int[] sourceSentence = corpus.getSourceSentence(i,
					BilingualCorpus.TRAIN_CORPUS);
			int[] foreignSentece = corpus.getForeignSentence(i,
					BilingualCorpus.TRAIN_CORPUS);
			;
			nrIndices = addPos(sourceSentence, foreignSentece, nrIndices);
		}

		// Go for test sentence if exits
		if (corpus.getNumSentences(BilingualCorpus.TEST_CORPUS) != 0) {
			for (int i = 0; i < corpus
					.getNumSentences(BilingualCorpus.TEST_CORPUS); i++) {
				int[] sourceSentence = corpus.getSourceSentence(i,
						BilingualCorpus.TEST_CORPUS);
				int[] foreignSentece = corpus.getForeignSentence(i,
						BilingualCorpus.TEST_CORPUS);
				nrIndices = addPos(sourceSentence, foreignSentece, nrIndices);
			}
		}
		// Go for dev sentences if exist

		if (corpus.getNumSentences(BilingualCorpus.DEV_CORPUS) != 0) {
			for (int sentenceNr = 0; sentenceNr < corpus
					.getNumSentences(BilingualCorpus.DEV_CORPUS); sentenceNr++) {
				int[] sourceSentence = corpus.getSourceSentence(sentenceNr,
						BilingualCorpus.DEV_CORPUS);
				int[] foreignSentece = corpus.getForeignSentence(sentenceNr,
						BilingualCorpus.DEV_CORPUS);
				nrIndices = addPos(sourceSentence, foreignSentece, nrIndices);
			}
		}
		// Compact hastables
		for (int i = 0; i < corpus.getSourceSize(); i++) {
			indices[i].compact();
		}	
	}
	
	public Reference(BilingualCorpus corpus) {
		initialize(corpus);
	}

	public final int getSize() {
		return nrIndices;
	}

	public final int getIndex(int sourceWord, int foreignWord) {
		if (!indices[sourceWord].contains(foreignWord)) {
			return -1;
		}
		return indices[sourceWord].get(foreignWord);
	}

	public final int getNumberIForeign(int sourceWord) {
		return indices[sourceWord].size();
	}

	// It is returning the absolute position for a given source index
	public final int[] getForeignIndices(int sourceWord) {
		return indices[sourceWord].getValues();
	}


}
